package com.ms.orm.meta;


import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Types;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * java bean 字段默认的基础数据类型，其他类型需要扩展
 * @author zdh
 */
public final class JavaTypeMapperJdbcType {

    /**
     * 未知的数据类型
     */
    public static final int TYPE_UNKNOW = Integer.MIN_VALUE;


    /**
     * sql数据类型 映射 Java数据类型
     */
    public static final Map<Integer, Class<?>> SQL_TYPE_TO_JAVA_TYPE ;


    public static final Map<Class<?>, Integer> JAVA_TYPE_TO_SQL_TYPE;

    static {

        //key=jdbcType,value=javaType
        Map<Integer, Class<?>> types = new HashMap<>();
        types.put(Types.INTEGER, Integer.class);
        types.put(Types.BIGINT, Long.class);
        types.put(Types.CHAR, String.class);
        types.put(Types.DECIMAL, BigDecimal.class);
        types.put(Types.NUMERIC, Number.class);

        types.put(Types.VARCHAR, String.class);
        types.put(Types.LONGVARCHAR, String.class);
        types.put(Types.LONGVARBINARY, byte[].class);
        types.put(Types.BINARY, byte[].class);

        types.put(Types.CLOB, String.class);

        types.put(Types.FLOAT, Float.class);
        types.put(Types.REAL, Float.class);
        types.put(Types.DOUBLE, Double.class);

        types.put(Types.BOOLEAN, Boolean.class);

        types.put(Types.SMALLINT, Short.class);
        types.put(Types.TINYINT, Byte.class);

        types.put(Types.DATE, Date.class);
        types.put(Types.TIME, Date.class);
        types.put(Types.TIME_WITH_TIMEZONE, Date.class);
        types.put(Types.TIMESTAMP, Date.class);
        types.put(Types.TIMESTAMP_WITH_TIMEZONE, Date.class);

        types.put(Types.BIT, boolean.class);
        SQL_TYPE_TO_JAVA_TYPE = Collections.unmodifiableMap(types);


        Map<Class<?>, Integer> basicTypes = new HashMap<>();
        basicTypes.put(int.class, Types.INTEGER);
        basicTypes.put(long.class, Types.BIGINT);
        basicTypes.put(short.class, Types.SMALLINT);
        basicTypes.put(byte.class, Types.TINYINT);
        basicTypes.put(float.class, Types.FLOAT);
        basicTypes.put(double.class, Types.DOUBLE);
        basicTypes.put(boolean.class, Types.BOOLEAN);

        basicTypes.put(Integer.class, Types.INTEGER);
        basicTypes.put(Long.class, Types.BIGINT);
        basicTypes.put(Short.class, Types.SMALLINT);
        basicTypes.put(Byte.class, Types.TINYINT);
        basicTypes.put(Float.class, Types.FLOAT);
        basicTypes.put(Double.class, Types.DOUBLE);
        basicTypes.put(Boolean.class, Types.BOOLEAN);

        basicTypes.put(String.class, Types.VARCHAR);
        basicTypes.put(BigDecimal.class, Types.NUMERIC);
        basicTypes.put(BigInteger.class, Types.NUMERIC);
        basicTypes.put(Number.class, Types.NUMERIC);

        basicTypes.put(java.time.LocalDateTime.class, Types.TIMESTAMP);
        basicTypes.put(java.time.LocalDate.class, Types.DATE);
        basicTypes.put(java.time.LocalTime.class, Types.TIME);

        basicTypes.put(java.util.Date.class, Types.TIMESTAMP);
        basicTypes.put(java.util.Calendar.class, Types.TIMESTAMP);
        basicTypes.put(java.sql.Date.class, Types.DATE);
        basicTypes.put(java.sql.Time.class, Types.TIME);
        basicTypes.put(java.sql.Timestamp.class, Types.TIMESTAMP);
        basicTypes.put(byte[].class, Types.BINARY);

        //转成不可修改的map，即不能添加、修改、删除
        JAVA_TYPE_TO_SQL_TYPE = Collections.unmodifiableMap(basicTypes);
    }


    /**
     * 根据数据字段类型 获取对于的java类型
     * @param sqlType
     * @return
     */
    public static Class<?> getJavaType(int sqlType) {
        return SQL_TYPE_TO_JAVA_TYPE.get(sqlType);
    }

    /**
     * 根据Java 类型 获取数据库字段类型
     * @param cls
     * @return
     */
    public static int getSqlType(Class<?> cls){
        Integer type = JAVA_TYPE_TO_SQL_TYPE.get(cls);
        if(type==null){
            type = new Integer(TYPE_UNKNOW);
        }
        return type.intValue();
    }

    /**
     * 获取数据库字段 类型
     * @param value
     * @return
     */
    public static int getSqlType(Object value){
        if(value==null){
            return TYPE_UNKNOW;
        }
        return getSqlType(value.getClass());
    }


}
